<template>
  <div ref="container" class="scene-container"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import * as dat from "dat.gui";
/**
 * 认识point
 */
// 给当前组件定义名称
defineOptions({
  name: "ThreeScene",
});

const container = ref<HTMLElement>();
let scene: THREE.Scene;
let camera: THREE.PerspectiveCamera;
let renderer: THREE.WebGLRenderer;
let controls: OrbitControls;
let sphere: THREE.Mesh;
let plane: THREE.Mesh;
let spotLight: THREE.SpotLight;
let smallBall: THREE.Mesh;
let points: THREE.Points;
//设置时钟
let clock = new THREE.Clock();
// 初始化场景
const initScene = () => {
  // 创建场景
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x000000); // 设置较暗的背景色
  // 创建相机
  camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  camera.position.set(0, 0, 40);
  scene.add(camera);

  const particlesGeometry = new THREE.BufferGeometry(); //创建点几何体
  const count = 5000; // 点数
  // 设置缓冲区数组
  const positions = new Float32Array(count * 3); //创建一个包含count*3个元素的Float32Array数组
  //设置粒子顶点颜色
  const colors = new Float32Array(count * 3); //创建一个包含count*3个元素的Float32Array数组
  //设置顶点
  for (let i = 0; i < count * 3; i++) {
    // positions[i] = Math.random() * 5;
    //全方位点，不单单正数
    positions[i] = (Math.random() - 0.5) * 100;

    // positions[i * 3] = (Math.random() - 0.5) * 10;
    // positions[i * 3 + 1] = (Math.random() - 0.5) * 10;
    // positions[i * 3 + 2] = (Math.random() - 0.5) * 10;
    colors[i] = Math.random();
  }
  //设置顶点
  particlesGeometry.setAttribute(
    "position",
    new THREE.BufferAttribute(positions, 3)
  );
  //设置顶点颜色
  particlesGeometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));
  const textureLoader = new THREE.TextureLoader();
  const texture = textureLoader.load(
    "/textures/PNG (Black background)/snow.png"
  );

  //创建点的材质
  const pointMaterial = new THREE.PointsMaterial({
    size: 1, // 调整点的大小
    sizeAttenuation: true, // 启用大小衰减
    map: texture, // 设置纹理贴图
    alphaMap: texture, // 设置透明度贴图
    transparent: true, // 启用透明
    depthWrite: false, // 禁用深度写入
    blending: THREE.AdditiveBlending, // 使用叠加混合-叠加更亮
    color: 0xffffff, // 设置颜色（可选）
  });
  //设置启用顶点颜色
  pointMaterial.vertexColors = false; //开启之后必须设置顶点颜色，否则不显示
  //删除points的uv
  particlesGeometry.deleteAttribute("uv");
  //创建点
  points = new THREE.Points(particlesGeometry, pointMaterial);

  scene.add(points);

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.shadowMap.enabled = true; // 开启阴影
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  container.value?.appendChild(renderer.domElement);
  // 添加坐标轴辅助
  const axesHelper = new THREE.AxesHelper(100);
  // scene.add(axesHelper);

  // 添加聚光灯辅助
  // const spotLightHelper = new THREE.SpotLightHelper(spotLight);
  // scene.add(spotLightHelper);

  // 添加轨道控制器
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.dampingFactor = 0.5;

  // 开始动画循环
  animate();
};

// 动画循环函数
const animate = () => {
  let time = clock.getElapsedTime();
  points.rotation.x = time * 0.2;
  points.rotation.y = time * 0.05;
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
};

// 处理窗口大小变化
const handleResize = () => {
  if (camera && renderer) {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  }
};

// 组件挂载时初始化
onMounted(() => {
  initScene();
  window.addEventListener("resize", handleResize);
});

// 组件卸载时清理
onBeforeUnmount(() => {
  window.removeEventListener("resize", handleResize);
});
</script>

<style scoped>
.scene-container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
</style>
